﻿using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// PresentationWindow.xaml 的交互逻辑
    /// </summary>
    public partial class PresentationWindow : Window
    {
        public PresentationWindow(MarkdownEditor editor)
        {
            InitializeComponent();
            this.masterEditor = editor;
        }

        private MarkdownEditor masterEditor = null;

        public MarkdownEditor MasterEditor
        {
            get { return this.masterEditor; }
        }

        private List<Question> questions = new List<Question>();
        private int point;

        public void BuildQuestions(string content)
        {
            this.questions.Clear();
            this.point = -1;

            //分解试题源文本，分解成试题列表。
            if (string.IsNullOrEmpty(content))
            {
                this.ShowQuestion();
                return;
            }

            int index = content.IndexOf("＜信息＞＞＞");
            if (index >= 0)
            {
                content = content.Substring(index + 6);
            }

            List<string> baseQuestionStrings = new List<String>();

            int previewIndex = -1;
            index = content.IndexOf("试题＞＞");

            while (index >= 0 && index < content.Length)
            {
                if (previewIndex > -1 && previewIndex <= index)
                {
                    String baseQuestionText = content.Substring(previewIndex, index - previewIndex);
                    baseQuestionStrings.Add(baseQuestionText);
                }

                previewIndex = index;
                index = content.IndexOf("试题＞＞", index + 4);
            }

            if (previewIndex >= 0 && index < 0)
            {
                // 最后一道题
                baseQuestionStrings.Add(content.Substring(previewIndex));
            }
            else
            {
                baseQuestionStrings.Add(content);
            }

            foreach (string baseQuestionString in baseQuestionStrings)
            {
                List<Question> newQuestions = BaseQuestion.BuildQuestionList(baseQuestionString, cmboxFillBlankView.SelectedItem == cbiMultiFillBlankQuestions);
                if (newQuestions != null)
                {
                    this.questions.AddRange(newQuestions);
                }
            }

            //根据是否“分拆”决定是否总体混淆排序
            if (cmboxFillBlankView.SelectedItem == cbiSingleQuestion)
            {
                // 使用随机数混淆顺序。
                int[] random = L.GetRandomIntArray(questions.Count);
                foreach (int i in random)
                {
                    questions[i].OrderNumber = random[i];
                }

                questions.Sort(new CmparsionQuestion());
            }

            if (questions.Count > 0)
            {
                point = 0;
            }
            else
            {
                point = -1;
            }

            this.ShowQuestion();//能不能显示，此方法自己可以管理。
        }

        private bool answerVisible = false;
        /// <summary>
        /// 当前是否显示了答案。
        /// </summary>
        public bool AnswerVisible
        {
            get { return this.answerVisible; }
        }

        private Run answerRun = null;
        private TextBlock answerTextBlock;

        private void ShowQuestion()
        {
            this.askPanel.Visibility = Visibility.Collapsed;//隐藏提问面板。

            this.answerVisible = false;
            this.answerParagraph = null;
            this.answerParagraphList.Clear();

            this.Document.Blocks.Clear();

            if (this.questions.Count <= 0)
            {
                this.Document.Blocks.Add(new Paragraph(new Run("文档中没有任何可以显示的试题！")));
                return;
            }

            if (this.point < 0)
            {
                this.Document.Blocks.Add(new Paragraph(new Run("试题指针越界（小于0）！")));
                return;
            }

            if (this.point >= this.questions.Count)
            {
                this.Document.Blocks.Add(new Paragraph(new Run("试题指针越界（大于可用试题总数）！")));
                return;
            }

            //带一对方括弧的是填充项。
            var question = questions[point];
            switch (question.Type)
            {
                case QuestionType.Judge://判断题是特殊形式的选择题。
                case QuestionType.Choice:
                    {
                        ShowChoiceQuestion(question); break;
                    }
                case QuestionType.FillBlank:
                    {
                        ShowFillBlankQuestion(question); break;
                    }
                case QuestionType.Subjective:
                    {
                        ShowSubjectiveQuestion(question); break;
                    }
                case QuestionType.Text:
                    {
                        ShowText(question); break;
                    }
            }

            this.Document.Focus();
        }

        private void ShowSubjectiveQuestion(Question question)
        {
            string title = question.TitleString.Replace("\r\n", "");

            if (string.IsNullOrEmpty(title))
            {
                title = "阅读下列材料：";
            }
            //根据title生成段落。

            var p = new Paragraph();

            var container = new InlineUIContainer();
            var questionNumberTextBlock = new TextBlock()
            {
                //Background = Brushes.Gray,
                Foreground = Brushes.Red,
                Padding = new Thickness(0, 0, 10, 0),
                Margin = new Thickness(0, 0, 10, 0),
                Text = (point + 1).ToString() + "．",
                FontWeight = FontWeights.Bold,
            };

            container.Child = questionNumberTextBlock;

            p.Inlines.Add(container);

            p.Inlines.Add(title);

            this.answerRun = null;//主观题没有填充项。故无此run。

            this.Document.Blocks.Add(p);

            //材料部分。

            foreach (var s in question.Materials)
            {
                int indexOfcc = s.IndexOf("＜＜出处＞＞");
                if (indexOfcc >= 0)
                {
                    Paragraph newPara = new Paragraph(new Run(s.Substring(0, indexOfcc).Replace("\r\n", "")));
                    this.Document.Blocks.Add(newPara);

                    string clcc = s.Substring(indexOfcc + 6);
                    if (clcc.StartsWith("——") == false)
                    {
                        clcc = "——" + clcc;
                    }
                    Paragraph newParacc = new Paragraph(new Run(clcc)) { TextAlignment = TextAlignment.Right, Foreground = Brushes.DeepPink, };
                    this.Document.Blocks.Add(newParacc);
                }
                else
                {
                    Paragraph newPara = new Paragraph(new Run(s.Replace("\r\n", "")));
                    this.Document.Blocks.Add(newPara);
                }
            }

            this.Document.Blocks.Add(new Paragraph(new Run("请回答：")));

            //问题部分

            for (int i = 0; i < question.AsksList.Count; i++)
            {
                var s = question.AsksList[i];
                Paragraph newPara = new Paragraph(new Run("(" + (i + 1).ToString() + ")" + s.Replace("\r\n", "")));
                this.Document.Blocks.Add(newPara);
            }

            answerParagraph = new Paragraph(new Run("参考答案：")
            {
                Background = Brushes.Red,
                Foreground = Brushes.White,
            });

            //下面是答案部分。

            for (int i = 0; i < question.Answers.Count; i++)
            {
                var s = question.Answers[i];
                int indexOfjx = s.IndexOf("解析＞＞");
                if (indexOfjx >= 0)
                {
                    Paragraph newPara = new Paragraph(new Run("(" + (i + 1).ToString() + ")" + s.Substring(0, indexOfjx).Replace("\r\n", "")));
                    this.answerParagraphList.Add(newPara);

                    Paragraph newParacc = new Paragraph(new Run(s.Substring(indexOfjx + 6))) { TextAlignment = TextAlignment.Right, };
                    this.answerParagraphList.Add(newParacc);
                }
                else
                {
                    Paragraph newPara = new Paragraph(new Run("(" + (i + 1).ToString() + ")" + s.Replace("\r\n", "")));
                    this.answerParagraphList.Add(newPara);
                }
            }

            tbTitle.Text = this.Title = "试题演示（" + (this.point + 1).ToString() + " ∕ " + this.questions.Count.ToString() + "）";
        }

        #region 主观题专用

        private Paragraph answerParagraph;
        private List<Paragraph> answerParagraphList = new List<Paragraph>();

        #endregion

        private void ShowText(Question question)
        {
            string title = question.TitleString;

            //根据title生成段落。

            var p = new Paragraph();
            var container = new InlineUIContainer();
            var questionNumberTextBlock = new TextBlock()
            {
                //Background = Brushes.Gray,
                Foreground = Brushes.Red,
                Padding = new Thickness(0, 0, 10, 0),
                Margin = new Thickness(0, 0, 10, 0),
                Text = (point + 1).ToString() + "．",
                FontWeight = FontWeights.Bold,
            };

            container.Child = questionNumberTextBlock;

            p.Inlines.Add(container);

            //int startBracket, endBracket;
            //startBracket = title.IndexOf("【");
            //endBracket = title.IndexOf("】");

            //如果根本就没有提供任何填充项，说明只是普通文本，直接输出即可。
            //if (startBracket < 0 && endBracket < 0)
            //{
            p.Inlines.Add(title);
            //}

            this.Document.Blocks.Add(p);

            tbTitle.Text = this.Title = "试题演示（" + (this.point + 1).ToString() + " ∕ " + this.questions.Count.ToString() + "）";
        }

        private void HideRightColumn()
        {
            rightColumn.Width = new GridLength(0);
        }

        private void ShowRightColumn()
        {
            rightColumn.Width = new GridLength(1, GridUnitType.Star);
        }

        private void ShowImage(string imageRelativePath)
        {
            if (string.IsNullOrWhiteSpace(imageRelativePath))
            {
                img.Source = null;
                HideRightColumn();
                return;
            }

            if (this.masterEditor == null || string.IsNullOrEmpty(this.masterEditor.FullFilePath))
            {
                img.Source = null;
                HideRightColumn();
                return;
            }

            var pieces = imageRelativePath.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
            if (pieces.Length <= 0)
            {
                img.Source = null;
                HideRightColumn();
                return;
            }

            FileInfo thisFileInfo = new FileInfo(this.MasterEditor.FullFilePath);
            var directory = thisFileInfo.Directory;

            int x = 0;
            foreach (var s in pieces)
            {
                if (s == "..")
                {
                    directory = directory.Parent;
                    x++;
                }
                else
                {
                    var subPath = directory.FullName.EndsWith("\\") ? (directory.FullName + s) : (directory.FullName + "\\" + s);

                    if (Directory.Exists(subPath) == false)
                    {
                        if (WorkspaceTreeViewItem.IsValidateImageFilePath(subPath))
                        {
                            //就是目标
                            ShowRightColumn();
                            img.Source = new BitmapImage(new Uri(subPath));
                            return;
                        }

                        HideRightColumn();
                        img.Source = null;
                        return;
                    }
                    else
                    {
                        directory = new DirectoryInfo(subPath);
                        x++;
                    }
                }
            }

            if (x != pieces.Length - 1)
            {
                HideRightColumn();
                img.Source = null; return;
            }
        }

        private void ShowFillBlankQuestion(Question question)
        {
            string title = question.TitleString;

            ShowImage(question.MarkdownImagePath);

            //根据title生成段落。

            var p = new Paragraph();
            var container = new InlineUIContainer();
            var questionNumberTextBlock = new TextBlock()
            {
                //Background = Brushes.Gray,
                Foreground = Brushes.Red,
                Padding = new Thickness(0, 0, 10, 0),
                Margin = new Thickness(0, 0, 10, 0),
                Text = (point + 1).ToString() + "．",
                FontWeight = FontWeights.Bold,
            };

            container.Child = questionNumberTextBlock;

            p.Inlines.Add(container);

            int previewStartBacket = -1; int previewEndBracket = -1;
            int startBracket, endBracket;
            startBracket = title.IndexOf("【");
            endBracket = title.IndexOf("】");

            while (startBracket >= 0 && endBracket >= 0)
            {
                p.Inlines.Add(title.Substring(previewEndBracket + 1, startBracket - previewEndBracket - 1));

                p.Inlines.Add(new Span(new Run(" " + title.Substring(startBracket + 1, endBracket - startBracket - 1) + " ") { Foreground = Brushes.Transparent, })
                {
                    Foreground = Brushes.Red,
                    FontWeight = FontWeights.Black,
                    TextDecorations = TextDecorations.Underline,
                    Tag = "FillBlank",
                });

                previewEndBracket = endBracket;
                previewStartBacket = startBracket;

                startBracket = title.IndexOf("【", endBracket + 1);
                endBracket = title.IndexOf("】", endBracket + 1);
            }

            if (previewEndBracket >= 0 && previewEndBracket < title.Length - 1)
            {
                p.Inlines.Add(title.Substring(previewEndBracket + 1));
            }

            this.Document.Blocks.Add(p);

            tbTitle.Text = this.Title = "试题演示（" + (this.point + 1).ToString() + " ∕ " + this.questions.Count.ToString() + "）";

            //填空题十分简单，只需要显示title即可。无须添加任何选择项，也没有解析。
        }

        private void ShowChoiceQuestion(Question question)
        {
            string title = question.TitleString.Replace("\r", "").Replace("\n", "");

            ShowImage(question.MarkdownImagePath);

            //根据title生成段落。

            int startBracket, endBracket;
            startBracket = title.IndexOf("【");
            endBracket = title.IndexOf("】");

            if (startBracket < 0 || endBracket < 0) return;

            var p = new Paragraph();

            var container = new InlineUIContainer();
            var questionNumberTextBlock = new TextBlock()
            {
                //Background = Brushes.Gray,
                Foreground = Brushes.Red,
                Padding = new Thickness(0, 0, 10, 0),
                Text = (point + 1).ToString() + "．",
                FontWeight = FontWeights.Bold,
            };

            container.Child = questionNumberTextBlock;

            p.Inlines.Add(container);

            p.Inlines.Add(title.Substring(0, startBracket));

            var answerText = title.Substring(startBracket + 1, endBracket - startBracket - 1);

            this.answerRun = new Run()
            {
                Text = "【　　】",
                Foreground = Brushes.Red,
                //Tag = "FillBlank",//这个还是直接显示比较好
            };

            p.Inlines.Add(new Span(this.answerRun)
            {
                Foreground = Brushes.Red,
                FontWeight = FontWeights.Black,
                //TextDecorations = TextDecorations.Underline,
            });

            p.Inlines.Add(title.Substring(endBracket + 1));

            this.Document.Blocks.Add(p);

            //添加各选项

            //先需要混淆下顺序，否则会总选A了。
            int[] randomArray = L.GetRandomIntArray(question.ChoiceItems.Count);
            for (int i = 0; i < randomArray.Length; i++)
            {
                var qi = question.ChoiceItems[i];
                qi.OrderNumber = randomArray[i];
            }

            question.ChoiceItems.Sort(new CmparsionQuestionItem());

            string answerHeaderText = "未设置答案项";

            for (int i = 0; i < question.ChoiceItems.Count; i++)
            {
                ChoiceItem qi = question.ChoiceItems[i];

                Paragraph itemParagraph = new Paragraph();

                string choiceItemHeaderText = L.ConvertToAlpha(i + 1);

                var choiceItemTextBlock = new TextBlock()
                {
                    Text = choiceItemHeaderText,
                    FontWeight = FontWeights.Bold,
                    Padding = new Thickness(10, 0, 10, 0),
                    Margin = new Thickness(0, 0, 10, 0),
                };
                itemParagraph.Inlines.Add(choiceItemTextBlock);

                itemParagraph.Inlines.Add(new Run(qi.Text.Replace("\r\n", "")));

                this.Document.Blocks.Add(itemParagraph);

                string analysis = qi.AnalysisText.Replace("\r\n", "");
                if (string.IsNullOrEmpty(analysis) == false)
                {
                    Paragraph itemAnalisys = new Paragraph() { Foreground = Brushes.Transparent, TextIndent = 30, };

                    choiceItemTextBlock.Tag = itemAnalisys;
                    choiceItemTextBlock.MouseLeftButtonDown += numTextBlock_MouseLeftButtonDown;
                    choiceItemTextBlock.Background = Brushes.Gray;
                    choiceItemTextBlock.Foreground = Brushes.White;

                    itemAnalisys.Inlines.Add(new Run(analysis));
                    //this.Document.Blocks.Add(itemAnalisys);//改成单击选项标头时插入，这样可以在一开始就看到所有选项，而不是空缺大段空白。
                }

                if (qi.IsAnswer) answerHeaderText = choiceItemHeaderText.Replace(".", "");
            }


            tbTitle.Text = this.Title = "试题演示（" + (this.point + 1).ToString() + " ∕ " + this.questions.Count.ToString() + "）";

            Paragraph answerParagraph = new Paragraph();
            answerTextBlock = new TextBlock()
            {
                Text = "?",//问号，在Wingdings字体中是一手执笔的形象。
                ToolTip = "按F1或?显示",
                FontFamily = new System.Windows.Media.FontFamily("Wingdings"),
                FontWeight = FontWeights.Bold,
                Padding = new Thickness(12, 0, 10, 0),
                Margin = new Thickness(0, 0, 10, 0),
                Foreground = Brushes.White,
                Background = Brushes.Red,
            };

            answerTextBlock.MouseLeftButtonDown += answerTextBlock_MouseLeftButtonDown;

            answerParagraph.Inlines.Add(answerTextBlock);
            var answerRun = new Run(" " + answerHeaderText + " " + answerText)
            {
                Foreground = Brushes.Transparent,
                FontWeight = FontWeights.Bold,
            };
            answerTextBlock.Tag = answerRun;

            answerParagraph.Inlines.Add(answerRun);

            this.Document.Blocks.Add(answerParagraph);
        }

        void answerTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.ShowChoiceQuestionAnswer(this.answerTextBlock);
        }

        private void ShowChoiceQuestionAnswer(TextBlock answerTextBlock)
        {
            if (answerTextBlock == null) return;

            var answerRun = answerTextBlock.Tag as Run;
            if (answerRun == null) return;

            if (answerRun.Foreground == Brushes.Transparent)
            {
                answerRun.Foreground = Brushes.Red;

                if (this.answerRun != null)
                    this.answerRun.Foreground = Brushes.Red;

                this.answerVisible = true;
            }
            else
            {
                answerRun.Foreground = Brushes.Transparent;

                if (this.answerRun != null)
                    this.answerRun.Foreground = Brushes.Transparent;

                this.answerVisible = false;
            }
        }

        void numTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var textBlock = sender as TextBlock;
            if (textBlock == null || textBlock.Tag == null) return;

            ShowAnalysys(textBlock);
        }

        private void ShowAnalysys(TextBlock textBlock)
        {
            var paragraph = textBlock.Tag as Paragraph;
            if (paragraph == null) return;//有些选项没有解析。

            if (this.Document.Blocks.Contains(paragraph) == false)
            {
                this.Document.Blocks.InsertAfter((textBlock.Parent as InlineUIContainer).Parent as Paragraph, paragraph);
                textBlock.Background = Brushes.Transparent;
                textBlock.Foreground = Brushes.DarkBlue;
            }
            else
            {
                this.Document.Blocks.Remove(paragraph);
                textBlock.Background = Brushes.Gray;
                textBlock.Foreground = Brushes.White;
            }

            if (paragraph.Foreground != Brushes.Transparent)
            {
                paragraph.Foreground = Brushes.Transparent;
            }
            else
            {
                paragraph.Foreground = Brushes.Blue;
            }
        }

        private void btnNext_Click(object sender, RoutedEventArgs e)
        {
            if (this.point < this.questions.Count - 1)
            {
                this.point++;
                this.ShowQuestion();
            }
            else
            {
                LMessageBox.Show("已至最后一题！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning, "", null, this);
            }
        }

        private void btnPreview_Click(object sender, RoutedEventArgs e)
        {
            if (this.point > 0)
            {
                this.point--;
                this.ShowQuestion();
            }
            else
            {
                LMessageBox.Show("已至第一题！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning, "", null, this);
            }
        }

        private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
        {

            KeyStates ksLeftCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);
            KeyStates ksRightCtrl = Keyboard.GetKeyStates(Key.RightCtrl);
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);
            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLeftAlt = Keyboard.GetKeyStates(Key.LeftAlt);
            KeyStates ksRightAlt = Keyboard.GetKeyStates(Key.RightAlt);
            KeyStates ksLeftWin = Keyboard.GetKeyStates(Key.LWin);
            KeyStates ksRightWin = Keyboard.GetKeyStates(Key.RWin);

            bool isCtrl = ((ksLeftCtrl & KeyStates.Down) > 0 || (ksRightCtrl & KeyStates.Down) > 0);
            //bool isShift = ((ksLeftShift & KeyStates.Down) > 0 || (ksRightShift & KeyStates.Down) > 0);
            //bool isAlt = ((ksLeftAlt & KeyStates.Down) > 0 || (ksRightAlt & KeyStates.Down) > 0);
            //bool isWin = ((ksLeftWin & KeyStates.Down) > 0 || (ksRightWin & KeyStates.Down) > 0);

            if ((e.Key >= Key.A && e.Key <= Key.Z))
            {
                string alpha = L.GetAlpha(e.Key);
                for (int i = this.Document.Blocks.Count - 1; i >= 0; i--)
                {
                    var block = this.Document.Blocks.ElementAt(i);
                    var paragraph = block as Paragraph;
                    if (paragraph == null || paragraph.Inlines.Count <= 0) continue;

                    var uicontainer = paragraph.Inlines.FirstInline as InlineUIContainer;
                    if (uicontainer == null) continue;

                    var textBlock = uicontainer.Child as TextBlock;
                    if (textBlock == null || textBlock.Text.StartsWith(alpha) == false) continue;

                    ShowAnalysys(textBlock);
                    break;
                }
            }

            //数字键1到9，表示选择学生名册中第几批次（可以将一个班级分为几批）
            if (e.Key >= Key.D1 && e.Key <= Key.D9)
            {
                int index = e.Key - Key.D1;
                if (index < 0) index = 0;

                if (index > cmboxStudentsListFilenames.Items.Count - 1) index = cmboxStudentsListFilenames.Items.Count - 1;

                if (index >= 0 && index <= cmboxStudentsListFilenames.Items.Count - 1)
                {
                    cmboxStudentsListFilenames.SelectedIndex = index;
                }
                //如果索引越界，不起任何作用。
            }

            if (e.Key == Key.F1 || e.Key == Key.OemQuestion)
            {
                //这段是老代码，在新增加的“填空模式”下无法工作，而“答案”按钮可以正常工作。故去除之。
                //显示答案
                //string alpha = "?";
                //for (int i = this.Document.Blocks.Count - 1; i >= 0; i--)
                //{
                //    var block = this.Document.Blocks.ElementAt(i);
                //    var paragraph = block as Paragraph;
                //    if (paragraph == null || paragraph.Inlines.Count <= 0) continue;

                //    var uicontainer = paragraph.Inlines.FirstInline as InlineUIContainer;
                //    if (uicontainer == null) continue;

                //    var textBlock = uicontainer.Child as TextBlock;
                //    if (textBlock == null || textBlock.Text.StartsWith(alpha) == false) continue;

                //    ShowAnswer(textBlock);
                //    break;
                //}

                btnShowAnswer_Click(sender, e);
            }

            //if (isCtrl)
            //{
            //这三个快捷键是控件自带的。
            //if (e.Key == Key.OemMinus)
            //{
            //    if (this.Document.FontSize > 12)
            //    {
            //        this.Document.FontSize -= 2;
            //    }
            //}

            //if (e.Key == Key.OemPlus)
            //{
            //    if (this.Document.FontSize < 98)
            //    {
            //        this.Document.FontSize += 2;
            //    }
            //}

            //if (e.Key == Key.D0)
            //{
            //    this.Document.FontSize = 20;
            //}
            //}
            if (!isCtrl)
            {
                if (e.Key == Key.OemComma || e.Key == Key.OemOpenBrackets || e.Key == Key.OemMinus || e.Key == Key.Prior)//Prior,即PageUp
                {
                    if (this.point > 0)
                    {
                        this.point--;
                        this.ShowQuestion();
                    }
                    else
                    {
                        LMessageBox.Show("已至第一题！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning, "", null, this);
                    }

                    e.Handled = true;
                }

                if (e.Key == Key.OemPeriod || e.Key == Key.OemCloseBrackets || e.Key == Key.OemPlus || e.Key == Key.Next)//句号。Key.Next即Key.PageDown。
                {
                    if (this.AnswerVisible)
                    {
                        if (this.point < this.questions.Count - 1)
                        {
                            this.point++;
                            this.ShowQuestion();
                        }
                        else
                        {
                            LMessageBox.Show("已至最后一题！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning, "", null, this);
                        }
                    }
                    else
                    {
                        ShowAnswer();
                    }

                    e.Handled = true;
                }

                if (e.Key == Key.Escape)//因为理论上选项可能用到X，所以不能用X键来退出。
                {
                    if (this.askPanel.Visibility == Visibility.Visible)
                    {
                        this.askPanel.Visibility = Visibility.Collapsed;//隐藏提问面板。
                        e.Handled = true;
                        return;
                    }

                    this.Close();
                }

                //Tab键用于提问。
                if (e.Key == Key.Tab)
                {
                    AskSomeoneAQuestion();
                    e.Handled = true;
                }

                //Enter键用于显示答案。显示答案按钮设置为IsDefault即可
                //if (e.Key == Key.Enter)
                //{
                //    btnShowAnswer_Click(sender, e);
                //    e.Handled = true;
                //}
            }
        }

        private void btnExportQuestions_Click(object sender, RoutedEventArgs e)
        {
            this.Hide();

            if (this.questions.Count <= 0)
            {
                this.Document.Blocks.Add(new Paragraph(new Run("文档中没有任何可以提取的试题！")));
                this.Document.Focus();
                return;
            }

            StringBuilder sbQuestion = new StringBuilder();

            StringBuilder sbAnalysysAndAnswer = new StringBuilder();//answer专门添加而不是每题添加

            for (int indexOfQuestion = 0; indexOfQuestion < this.questions.Count; indexOfQuestion++)
            {
                var q = this.questions[indexOfQuestion];

                switch (q.Type)
                {
                    case QuestionType.Choice:
                    case QuestionType.Judge:
                        {
                            //带一对方括弧的是填充项。
                            string title = q.TitleString;

                            //根据title生成段落。
                            int startBracket, endBracket;
                            startBracket = title.IndexOf("【");
                            endBracket = title.IndexOf("】");

                            if (startBracket < 0 || endBracket < 0) break;

                            //题号
                            sbQuestion.Append((indexOfQuestion + 1).ToString() + "．");
                            sbAnalysysAndAnswer.Append((indexOfQuestion + 1).ToString() + "．");

                            string titleText = title.Substring(0, startBracket) + "（　 ）" + title.Substring(endBracket + 1);
                            if (titleText.EndsWith("\r\n") == false) titleText += "\r\n";
                            sbQuestion.Append(titleText);

                            //添加各选项

                            //先需要混淆下顺序，否则会总选A了。
                            int[] randomArray = L.GetRandomIntArray(q.ChoiceItems.Count);
                            for (int i = 0; i < randomArray.Length; i++)
                            {
                                var qi = q.ChoiceItems[i];
                                qi.OrderNumber = randomArray[i];
                            }

                            q.ChoiceItems.Sort(new CmparsionQuestionItem());

                            string answerHeaderText = "未设置答案项";

                            for (int i = 0; i < q.ChoiceItems.Count; i++)
                            {
                                ChoiceItem qi = q.ChoiceItems[i];
                                string choiceItemHeaderText = L.ConvertToAlpha(i + 1);
                                sbQuestion.Append(choiceItemHeaderText);
                                sbQuestion.Append(qi.Text.Replace("\r\n", ""));
                                sbQuestion.Append("\r\n");

                                string analysis = qi.AnalysisText.Replace("\r\n", "");

                                if (qi.IsAnswer) answerHeaderText = choiceItemHeaderText.Replace(".", "");

                                sbAnalysysAndAnswer.Append(choiceItemHeaderText);
                                sbAnalysysAndAnswer.Append(string.IsNullOrEmpty(analysis) ? "<此项未提供解析>" : analysis);
                                sbAnalysysAndAnswer.Append("\r\n");
                            }

                            sbQuestion.Append("\r\n\r\n");//每题之间空一行。

                            sbAnalysysAndAnswer.Append("----------\r\n【答案】" + answerHeaderText + "。\r\n\r\n");
                            break;
                        }
                    case QuestionType.FillBlank:
                        {
                            string answerHeaderText = "";

                            string title = q.TitleString;
                            int previewStartBacket = -1; int previewEndBracket = -1;
                            int startBracket, endBracket;
                            startBracket = title.IndexOf("【");
                            endBracket = title.IndexOf("】");

                            if (startBracket < 0 || endBracket < 0) break;

                            //题号
                            sbQuestion.Append((indexOfQuestion + 1).ToString() + "．");
                            sbAnalysysAndAnswer.Append((indexOfQuestion + 1).ToString() + "．");

                            int answerPieceNumber = 1;

                            while (startBracket >= 0 && endBracket >= 0)
                            {
                                sbQuestion.Append(title.Substring(previewEndBracket + 1, startBracket - previewEndBracket - 1));
                                string answerPiece = title.Substring(startBracket + 1, endBracket - startBracket - 1);
                                sbQuestion.Append(ReplaceWithUnderLine(answerPiece));

                                answerHeaderText += "[" + answerPieceNumber.ToString() + "]" + answerPiece + "　";

                                previewEndBracket = endBracket;
                                previewStartBacket = startBracket;

                                startBracket = title.IndexOf("【", endBracket + 1);
                                endBracket = title.IndexOf("】", endBracket + 1);

                                answerPieceNumber++;
                            }

                            sbQuestion.Append(title.Substring(previewEndBracket + 1) + "\r\n");

                            sbAnalysysAndAnswer.Append("【答案】" + answerHeaderText.Substring(0, answerHeaderText.Length - 1) + "。\r\n\r\n");

                            break;
                        }
                    case QuestionType.Subjective:
                        {
                            string title = q.TitleString.Replace("\r\n", "");

                            if (string.IsNullOrEmpty(title))
                            {
                                title = "阅读下列材料：";
                            }
                            //根据title生成段落。
                            sbQuestion.Append((indexOfQuestion + 1).ToString() + "．");
                            sbQuestion.Append(title);

                            //材料部分。

                            foreach (var s in q.Materials)
                            {
                                int indexOfcc = s.IndexOf("＜＜出处＞＞");
                                if (indexOfcc >= 0)
                                {
                                    sbQuestion.Append(s.Substring(0, indexOfcc).Replace("\r\n", "") + "\r\n");

                                    string clcc = s.Substring(indexOfcc + 6);
                                    if (clcc.StartsWith("——") == false)
                                    {
                                        clcc = "——" + clcc;
                                    }
                                    sbQuestion.Append(clcc + "\r\n");
                                }
                                else
                                {
                                    sbQuestion.Append(s.Replace("\r\n", "") + "\r\n");
                                }
                            }

                            sbQuestion.Append("请回答：\r\n");

                            //问题部分

                            for (int i = 0; i < q.AsksList.Count; i++)
                            {
                                var s = q.AsksList[i];
                                sbQuestion.Append("(" + (i + 1).ToString() + ")" + s.Replace("\r\n", "") + "\r\n");
                            }

                            sbQuestion.Append("\r\n");

                            //下面是答案部分。
                            sbAnalysysAndAnswer.Append((indexOfQuestion + 1) + "．");
                            for (int i = 0; i < q.Answers.Count; i++)
                            {
                                var s = q.Answers[i];
                                int indexOfjx = s.IndexOf("解析＞＞");
                                if (indexOfjx >= 0)
                                {
                                    sbAnalysysAndAnswer.Append("(" + (i + 1).ToString() + ")" + s.Substring(0, indexOfjx).Replace("\r\n", ""));
                                    sbAnalysysAndAnswer.Append(s.Substring(indexOfjx + 6));
                                }
                                else
                                {
                                    sbAnalysysAndAnswer.Append("(" + (i + 1).ToString() + ")" + s.Replace("\r\n", ""));
                                }
                            }
                            sbAnalysysAndAnswer.Append("\r\n\r\n");
                            break;
                        }
                }
            }

            Clipboard.SetText(sbQuestion.ToString() + sbAnalysysAndAnswer.ToString());
            LMessageBox.Show("此文档所有试题均已复制到剪贴板！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Information, "", null, this);

            this.Close();//便于操作。
        }

        private static string ReplaceWithUnderLine(string src)
        {
            if (string.IsNullOrEmpty(src)) return string.Empty;

            var sb = new StringBuilder();
            for (int i = 0; i <= src.Length; i++)//多加一对半角下划线字符。
            {
                sb.Append("__");
            }

            return sb.ToString();
        }

        private void btnShowAnswer_Click(object sender, RoutedEventArgs e)
        {
            ShowAnswer();
        }

        private void ShowAnswer()
        {
            //如果正在提问，隐藏提问面板
            if (askPanel.Visibility != System.Windows.Visibility.Collapsed)
            {
                askPanel.Visibility = System.Windows.Visibility.Collapsed;
            }

            if (this.point < 0 || this.point >= this.questions.Count) return;

            //this.answerVisible = true | false;//这个值由具体的ShowXXXAnswer()方法决定。

            switch (this.questions[this.point].Type)
            {
                case QuestionType.Judge://判断题是特殊的选择题。
                case QuestionType.Choice:
                    {
                        this.ShowChoiceQuestionAnswer(this.answerTextBlock);
                        break;
                    }
                case QuestionType.FillBlank:
                    {
                        this.ShowFillBlankQuestionAnswer(this.answerTextBlock);
                        break;
                    }
                case QuestionType.Subjective:
                    {
                        this.ShowSubjectiveQuestionAnswer(this.answerTextBlock);
                        break;
                    }
            }

            this.Document.Focus();
        }

        private void ShowSubjectiveQuestionAnswer(TextBlock textBlock)
        {
            if (this.answerParagraph == null) return;

            if (this.Document.Blocks.Contains(this.answerParagraph))
            {
                // 已处于显示答案状态，隐藏答案
                if (this.Document.Blocks.Contains(this.answerParagraph))
                {
                    this.Document.Blocks.Remove(this.answerParagraph);
                }

                for (int i = this.answerParagraphList.Count - 1; i >= 0; i--)
                {
                    if (this.Document.Blocks.Contains(this.answerParagraphList[i]))
                        this.Document.Blocks.Remove(this.answerParagraphList[i]);
                }

                this.answerVisible = false;
            }
            else
            {
                if (this.Document.Blocks.Contains(this.answerParagraph) == false)
                {
                    this.Document.Blocks.Add(this.answerParagraph);
                }

                foreach (var p in this.answerParagraphList)
                {
                    if (this.Document.Blocks.Contains(p) == false)
                        this.Document.Blocks.Add(p);
                }

                this.answerVisible = true;
            }

            ScrollViewer scrollViewer = GetScrollViewer(mainDocumentReader) as ScrollViewer;
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToEnd();
            }
        }

        public static DependencyObject GetScrollViewer(DependencyObject o)
        {
            // Return the DependencyObject if it is a ScrollViewer
            if (o is ScrollViewer)
            { return o; }

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
            {
                var child = VisualTreeHelper.GetChild(o, i);

                var result = GetScrollViewer(child);
                if (result == null)
                {
                    continue;
                }
                else
                {
                    return result;
                }
            }

            return null;
        }

        private void ShowFillBlankQuestionAnswer(TextBlock textBlock)
        {
            foreach (var block in this.Document.Blocks)
            {
                var paragraph = block as Paragraph;
                if (paragraph == null) continue;

                foreach (var inline in paragraph.Inlines)
                {
                    var span = inline as Span;
                    if (span == null) continue;

                    if (span.Tag.ToString() == "FillBlank")
                    {
                        foreach (var run in span.Inlines)
                        {
                            var answerRun = run as Run;
                            if (answerRun == null) continue;

                            if (answerRun.Foreground == Brushes.Transparent)
                            {
                                answerRun.Foreground = Brushes.Red;

                                if (answerVisible != true)
                                {
                                    answerVisible = true;
                                }
                            }
                            else
                            {
                                answerRun.Foreground = Brushes.Transparent;

                                if (answerVisible != false)
                                {
                                    answerVisible = false;
                                }
                            }
                        }
                    }
                }
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            #region 载入学生名册列表
            try
            {
                cmboxStudentsListFilenames.Items.Clear();

                string studentListDirectoryPath = Globals.PathOfUserFolder + (Globals.PathOfUserFolder.EndsWith("\\") ? "" : "\\") + "StudentsLists\\";
                if (Directory.Exists(studentListDirectoryPath) == false)
                {
                    Directory.CreateDirectory(studentListDirectoryPath);
                }

                DirectoryInfo studentListDirectoryinfo = new DirectoryInfo(studentListDirectoryPath);
                FileInfo[] childFiles = studentListDirectoryinfo.GetFiles();

                if (childFiles.Count<FileInfo>() <= 0)
                {
                    var sampleClassFilePath = studentListDirectoryPath + "SampleClass.txt";
                    if (File.Exists(sampleClassFilePath) == false)
                    {
                        File.WriteAllText(sampleClassFilePath, Properties.Resources.SampleClassFileContent);
                    }
                }

                var directoryInfo = new DirectoryInfo(studentListDirectoryPath);
                var fileInfos = directoryInfo.GetFiles();

                foreach (var fi in fileInfos)
                {
                    cmboxStudentsListFilenames.Items.Add(new ComboBoxItem() { Content = fi.Name, });
                }

                var selectedStudentListShortFileName = App.ConfigManager.Get("SelectedStudentListShortFileName");
                if (selectedStudentListShortFileName != null && selectedStudentListShortFileName != string.Empty)
                {
                    ComboBoxItem cbi = null;
                    foreach (var i in cmboxStudentsListFilenames.Items)
                    {
                        var ii = i as ComboBoxItem;
                        if (ii == null) continue;

                        if (ii.Content.ToString() == selectedStudentListShortFileName)
                        {
                            cbi = ii;
                            break;
                        }
                    }

                    if (cbi != null)
                    {
                        var newIndex = cmboxStudentsListFilenames.Items.IndexOf(cbi);
                        cmboxStudentsListFilenames.SelectedIndex = newIndex;
                    }
                    else
                    {
                        if (cmboxStudentsListFilenames.Items.Count > 0)
                        {
                            cmboxStudentsListFilenames.SelectedIndex = 0;
                        }
                    }
                }
                else
                {
                    if (cmboxStudentsListFilenames.Items.Count > 0)
                    {
                        cmboxStudentsListFilenames.SelectedIndex = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                LMessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.None, "", null, this);
            }
            #endregion 载入学生名册


            //载入缩放比例
            string zoomText = App.ConfigManager.Get("Zoom");
            if (string.IsNullOrEmpty(zoomText) == false)
            {
                try
                {
                    double zoom = double.Parse(zoomText);
                    mainDocumentReader.Zoom = zoom;
                }
                catch (Exception)
                {
                    mainDocumentReader.Zoom = 150;
                }
            }

            //载入填空题演示模式
            string fillBlankMode = App.ConfigManager.Get("MultiFillBlankMode");
            if (string.IsNullOrEmpty(fillBlankMode) == false)
            {
                if (fillBlankMode == true.ToString())
                {
                    cmboxFillBlankView.SelectedIndex = 0;//源填空题中有几个填空项，仍作一题显示。
                }
                else
                {
                    cmboxFillBlankView.SelectedIndex = 1;//每填空项拆分成一道填空题，且乱序排列。
                }
            }

            Globals.SwitchInputMethod(false);
            this.Document.Focus();
        }

        private void Window_Activated(object sender, EventArgs e)
        {
            Globals.SwitchInputMethod(false);
            this.Document.Focus();
        }

        private void cmboxFillBlankView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.BuildQuestions(ContentText);
        }


        public string ContentText { get; set; }

        //如果在演示主观题，滚轮去除滚动、PageDown/PageUp又去除功能，还怎么滚动呢？
        //private void FlowDocumentReader_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        //{
        //    if (e.Delta < 0)
        //    {
        //        btnNext_Click(sender, e);
        //    }
        //    else
        //    {
        //        btnPreview_Click(sender, e);
        //    }

        //    e.Handled = true;
        //}

        private void AskSomeoneAQuestion()
        {
            var student = this.GetAStudent();
            if (student == null)
            {
                tbkStudentName.Text = "<未设置名册>";
            }
            else
            {
                tbkStudentName.Text = student.Number + "号 " + student.Name;
            }

            askPanel.Visibility = System.Windows.Visibility.Visible;
        }

        private void btnAskRandom_Click(object sender, RoutedEventArgs e)
        {
            this.AskSomeoneAQuestion();
        }

        private void cmboxStudentsListFilenames_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selItem = cmboxStudentsListFilenames.SelectedItem as ComboBoxItem;
            if (selItem == null) return;

            string fileShortName = selItem.Content as string;
            if (string.IsNullOrEmpty(fileShortName)) return;

            ReadStudentsFromFile(fileShortName);
        }

        private List<Student> students;

        private void ReadStudentsFromFile(string fileShortName)
        {
            if (students == null)
            {
                students = new List<Student>();
            }
            students.Clear();

            if (string.IsNullOrEmpty(fileShortName))
            {
                return;
            }
            //先看文件在何处。

            string studentListFileFullPath = Globals.PathOfUserFolder + (Globals.PathOfUserFolder.EndsWith("\\") ? "" : "\\") + "StudentsLists\\" + fileShortName;
            if (File.Exists(studentListFileFullPath))
            {
                using (StreamReader sr = new StreamReader(studentListFileFullPath))
                {
                    while (!sr.EndOfStream) //读到结尾退出
                    {
                        string strLine = sr.ReadLine(); strLine = strLine.Trim();

                        if (strLine.Length == 0) continue;

                        if (strLine.StartsWith("//")) continue;//这个用作备注。

                        if (strLine.Contains("//"))
                        {
                            strLine = strLine.Substring(0, strLine.IndexOf("//"));
                        }

                        if (string.IsNullOrEmpty(strLine)) continue;

                        //将每一行拆分，分隔符就是char 数组中的字符
                        string[] stringPieces = strLine.Split(new char[] { '\t', ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                        //将拆分好的string[] 存入list
                        if (stringPieces.Length == 2)
                        {
                            students.Add(new Student() { Name = stringPieces[1], Number = stringPieces[0], });
                        }

                    }
                }
            }

            RandomStudents();
        }

        private void RandomStudents()
        {
            if (studentPoint >= students.Count)
            {
                studentPoint = 0;
            }

            //混淆。
            int[] random = L.GetRandomIntArray(students.Count);
            foreach (int i in random)
            {
                students[i].OrderNumber = random[i];
            }
            students.Sort(new CmparsionStudent());

        }

        private int studentPoint = 0;

        private Student GetAStudent()
        {
            if (students == null || students.Count <= 0) return null;

            var student = students[studentPoint];

            studentPoint++;

            //重新混淆一次。
            if (studentPoint >= students.Count)
            {
                RandomStudents();
                studentPoint = 0;
            }

            return student;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.Hide();

            //在配置文件在存储缩放比例。
            App.ConfigManager.Set("Zoom", mainDocumentReader.Zoom.ToString());

            //在配置文件中存储当前使用的学生名册
            if (cmboxStudentsListFilenames.SelectedItem != null)
            {
                var cbi = cmboxStudentsListFilenames.SelectedItem as ComboBoxItem;
                if (cbi != null)
                {
                    App.ConfigManager.Set("SelectedStudentListShortFileName", cbi.Content.ToString());
                }
            }

            //在配置文件中保存“填空题显示模式”
            if (cmboxFillBlankView.SelectedIndex == 0)
            {
                App.ConfigManager.Set("MultiFillBlankMode", true.ToString());
            }
            else if (cmboxFillBlankView.SelectedIndex == 1)
            {
                App.ConfigManager.Set("MultiFillBlankMode", false.ToString());
            }

            e.Cancel = true;
        }
    }

    class CmparsionQuestionItem : IComparer<ChoiceItem>
    {
        public int Compare(ChoiceItem x, ChoiceItem y)
        {
            return x.OrderNumber.CompareTo(y.OrderNumber);
        }
    }

    class CmparsionQuestion : IComparer<Question>
    {
        public int Compare(Question x, Question y)
        {
            return x.OrderNumber.CompareTo(y.OrderNumber);
        }
    }

    public class Student
    {
        private string number = string.Empty;

        public string Number
        {
            get
            {
                return this.number;
            }
            set { this.number = value; }
        }

        private string name = "无名氏";

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public int OrderNumber { get; set; }
    }

    class CmparsionStudent : IComparer<Student>
    {
        public int Compare(Student x, Student y)
        {
            return x.OrderNumber.CompareTo(y.OrderNumber);
        }
    }
}
